/*
 * Recipe class
 */

package bakenote.core;

import org.apache.pivot.collections.ArrayList;
import org.apache.pivot.collections.List;
import org.apache.pivot.collections.ListListener;

import java.util.UUID;
import java.io.File;


/**
 * @author lello
 */
public class Recipe {

    // Unique Universal identification number of the recipe
    private UUID uuid = null;
    private String name = ""; // = "Bread"; // name of the formulaList (default to Bread)
    private String author = "";
    private String source = "";
    private String type = "";
    private String tag = "";
    private int rating = 0; // how good the recipe is considered
    private int level = 0; // level of difficulty // unused
    private double amount = 1000.0d; // unused
    private File file;
    private List<Formula> formulaList = new ArrayList<Formula>();
    private List<Double> amountList = new ArrayList<Double>();
    private Procedure procedure = null;
    private String note ="";

    public Recipe() {
    }

    public Recipe(String s) {
        name = s;
    }

    public Recipe(ArrayList<Formula> fl) {
        formulaList = fl;
    }

    /**
     * Copy constructor
     *
     * @param r
     */
    public Recipe(Recipe r) {

        System.out.println("creating copy of recipe "+r.getUUID());

        this.uuid = r.uuid;
        this.name = r.getName();
        this.author = r.getAuthor();
        this.source = r.getSource();
        this.type = r.getType();
        this.tag = r.getTag();
        this.amount = r.getAmount();
        this.level = r.getLevel();
        this.rating = r.getRating();
        for (Formula f : r.getFormulaList()) {
            // copy constructor of formula
            this.formulaList.add(new Formula(f));
            this.amountList.add(f.getAmount());
        }
        for (int i = 0; i < formulaList.getLength(); i++) {
            final int updatedFormula = i;
            formulaList.get(i).getIngredients().getListListeners().add(new ListListener.Adapter() {
                @Override
                public void itemUpdated(List list, int i, Object o) {
                    Ingredient previousIngredient = (Ingredient) o;
                    if (previousIngredient.getAmount().isMeasurable()) {
                        double ratio = previousIngredient.getAmount().getDouble() / previousIngredient.getExactPercent();
                        updateIngredientsAmount(updatedFormula, ratio);
                    }
                }
            });
        }
        if (r.getProcedure() != null) this.procedure = r.getProcedure();// new Procedure(r.getProcedure());
        this.note = r.getNote();
    }

    private void updateIngredientsAmount(int updatedFormula, double ratio) {

        double oldAmount = amountList.get(updatedFormula);
        // First we update the edited formula...
        for (Ingredient ing : formulaList.get(updatedFormula).getIngredients()) {
            if (ing.getAmount().isMeasurable()) {
                double newAmount = (ing.getExactPercent()) * ratio;
                ing.setAmount(newAmount);
            }
        }
        formulaList.get(updatedFormula).setAmount();
        double newAmount = formulaList.get(updatedFormula).getAmount();
        double newRatio = newAmount / oldAmount;
        amountList.update(updatedFormula, newAmount);

        //...then we update all the remaining formulae
        for (int i = 0; i < formulaList.getLength(); i++) {
            if (i != updatedFormula) {
                for (Ingredient ing : formulaList.get(i).getIngredients()) {
                    if (ing.getAmount().isMeasurable()) {
                        //double newAmount = (ing.getExactPercent()) * ratio;
                        double newIngredientAmount = (ing.getAmount().getDouble()) * newRatio;
                        ing.setAmount(newIngredientAmount);
                    }
                }
                formulaList.get(i).setAmount();
                double newFormulaAmount = formulaList.get(i).getAmount();
                amountList.update(i, newFormulaAmount);
            }
        }
    }

    public boolean equals(Recipe r) {
        return (r.getUUID().equals(this.getUUID()));
    }

    public void setAmount(double f) {
        amount = f;
    }

    public double getAmount() {
        double fa = 0.0d;
        for (Formula f : formulaList) {
            fa += f.getAmount();
        }
        return fa;
    }

    public int getRating() {
        return rating;
    }

    public void setRating(int r) {
        rating = r;
    }

    public int getLevel() {
        return level;
    }

    public void setLevel(int l) {
        level = l;
    }

    public List<Formula> getFormulaList() {
        return formulaList;
    }

    public void removeFormula(Formula f) {
        formulaList.remove(f);
    }

    public void removeFormula(int i) {
        formulaList.remove(i, 1);
    }

    public void addFormula(Formula f) {
        formulaList.add(f);
    }

    public void addFormula() {
        formulaList.add(new Formula());
    }

    public void addFormula(int i) {
        //formulaList.add(i, new Formula());
        formulaList.insert(new Formula(), i);
    }

    public Formula getFormula(int i) {
        return formulaList.get(i);
    }

    public void setFormulaList(List<Formula> fList) {
        if (!formulaList.isEmpty()) {
            // Remove previous formulae from the recipe (if we are editing an existing recipe)
            for (int i = formulaList.getLength() - 1; i >= 0; i--) {
                this.removeFormula(i);
            }
        }

        // Add formula to the recipe
        for (int i = 0; i < fList.getLength(); i++) {
            //System.out.println("adding formula "+i);
            this.addFormula(fList.get(i));
        }
        // Find bakers' percent and set the percent of each formula
        double totAmount = getAmount();
        for (Formula form : this.formulaList) {
            if (form.AUTOPERCENT) {
                form.BakersPercent();
            }
            form.setPercent(form.getAmount() / totAmount);
        }
    }

    /**
     * public Object[] list() {
     * return formulaList.toArray();
     * }  *
     */

    public String getName() {
        return name;
    }

    public void setName(String s) {
        name = s;
    }

    public String getType() {
        return type;
    }

    public void setType(String s) {
        type = s;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String s) {
        author = s;
    }

    public void setTag(String tag) {
        //for (int i = 0; i<tags.length;i++) System.out.println(tags[i]);
        this.tag = tag;
    }

    public String getTag() {
        return tag;
    }

    public void setSource(String s) {
        source = s;
    }

    public String getSource() {
        return source;
    }

    // This is used by the JTree class to define the actually displayed text in the tree
    @Override
    public String toString() {
        return name;
    }

    public boolean contains(String s) {
        String slow = s.toLowerCase();
        boolean b1 = name.toLowerCase().contains(slow);
        boolean b2 = false;
        if (author != null) b2 = author.toLowerCase().contains(slow);
        boolean b3 = false;
        if (source != null) b3 = source.toLowerCase().contains(slow);
        boolean bf = false;
        for (Formula f : formulaList) {
            bf = f.contains(slow);
        }
        return b1 || b2 || b3 || bf;
    }

    public String getUUID() {
        //System.out.println("Getting Key " + uuid);
        return uuid.toString();
    }

    public void setUUID(String s) {
        uuid = UUID.fromString(s);
        //System.out.println("Setting Key " + uuid);
    }

    public void createUUID() {
        uuid = UUID.randomUUID();
        //System.out.println("Create Key " + uuid);
    }

    public Procedure getProcedure() {
        return procedure;
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note;
    }

    public void setProcedure(Procedure procedure) {
        this.procedure = procedure;
    }

    /**
    public static class Builder {

        private UUID uuid = null;
        private String title = ""; // = "Bread"; // name of the formulaList (default to Bread)
        private String author = "";
        private String source = "";
        private String type = "";
        private double amount = 1000.0d;
        private File file;
        private List<String> tag = new ArrayList<String>(); // assign tags to the recipe for easy search
        private List<Formula> formula = new ArrayList<Formula>();

        public Builder(String title) {
            this.title = title;
        }

        public Builder author(String a) {
            this.author = a;
            return this;
        }

        public Builder source(String s) {
            this.source = s;
            return this;
        }

        public Builder type(String t) {
            this.type = t;
            return this;
        }

        public Builder addFormula(Formula f) {
            this.formula.add(f);
            return this;
        }

        public Recipe build() {
            return new Recipe(this);
        }
    }

    public Recipe(Builder builder) {
        this.uuid = builder.uuid;
        this.name = builder.title;
        this.author = builder.author;
        this.formulaList = builder.formula;
        this.source = builder.source;
    }  **/

}
